﻿using System;

namespace rehot.plugin
{
#if NET20
    using System.Collections.Generic;
    using SanlieHash;
    [Serializable]
    public class RehotAssemblyContainer : MarshalByRefObject
    {
        internal RehotAssemblyLoader _loader { get; private set; }
        internal Dictionary<string, HotDLL> _caches { get; set; } = new Dictionary<string, HotDLL>();
        internal Queue<HotDLL> _dlls = new Queue<HotDLL>();
        internal RehotAssemblyContainer(RehotAssemblyLoader loader)
        {
            _loader = loader;
        }
        internal void Lose()
        {
            _loader = null;
            _caches.Clear();
            _caches = null;
            while (_dlls.Count != 0) _dlls.Dequeue().Dispose();
            _dlls = null;
        }
        public HotDLL UseDLL(string name)
        {
            var key = FastHash.GetSM3(name.ToLower());
            if (_loader._asms.ContainsKey(key))
            {
                if (_caches.ContainsKey(key)) return _caches[key];
                var dll = new HotDLL(_loader._asms[key]);
                _dlls.Enqueue(dll);
                _caches[key] = dll;
                return dll;
            }
            throw new DllNotFoundException(name);
        }
        public void Run(Action<RehotAssemblyContainer> func)
        {
            func(this);
        }
        public delegate T RUN_FUNCTION_RETURN<T>(RehotAssemblyContainer container);
        public T Run<T>(RUN_FUNCTION_RETURN<T> func)
        {
            return func(this);
        }
    }
#else
    using System.Collections.Generic;
    using SanlieHash;
    public class RehotAssemblyContainer
    {
        internal RehotAssembly _loader { get; private set; }
        internal Dictionary<string, HotDLL> _caches { get; set; } = new Dictionary<string, HotDLL>();
        internal Queue<HotDLL> _dlls = new Queue<HotDLL>();
        internal RehotAssemblyContainer(RehotAssembly loader)
        {
            _loader = loader;
        }
        internal void Lose()
        {
            _loader = null;
            _caches.Clear();
            _caches = null;
            while (_dlls.Count != 0) _dlls.Dequeue().Dispose();
            _dlls = null;
        }
        public HotDLL UseDLL(string name)
        {
            var key = FastHash.GetSM3(name.ToLower());
            if (_loader._asms.ContainsKey(key))
            {
                if (_caches.ContainsKey(key)) return _caches[key];
                var dll = new HotDLL(_loader._asms[key]);
                _dlls.Enqueue(dll);
                _caches[key] = dll;
                return dll;
            }
            throw new DllNotFoundException(name);
        }
        public void Run(Action<RehotAssemblyContainer> func)
        {
            func(this);
        }
        public delegate T RUN_FUNCTION_RETURN<T>(RehotAssemblyContainer container);
        public T Run<T>(RUN_FUNCTION_RETURN<T> func)
        {
            return func(this);
        }
    }
#endif
}
